﻿using DeHeng_Mes.Constant;
using DeHeng_Mes.Dao;
using DeHeng_Mes.Model.OrderSingleton;
using DeHeng_Mes.Model.Table;
using DeHeng_Mes.Utils;
using NPOI.SS.Formula.Functions;
using S7.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace DeHeng_Mes.PlcService
{
    public class VerificationService
    {
        #region 成员实例
        OrderDao orderDao = new OrderDao();
        #endregion

        public byte CodeVerification(string station, string code)
        {
            // 初始化报警码
            List<int> errorCodes = new List<int>();

            // 初始化NG状态列表
            List<bool> NgStatus = new List<bool>();

            // 初始化NG校验(有出站记录)
            bool ngStationIsGoOut = false;

            int count = 0;

            try
            {
                // 初始化防跳序状态
                bool operationIsOk = false;

                // 初始化防跳序错误码
                int errorcode = 0;

                foreach (var code in codes)
                {
                    // 格式校验
                    bool isOk = CodeIsOk(code);

                    // 重码校验
                    bool isSave = CodeIsSave(code, station);

                    // 产量校验
                    bool productionIsOk = OrderProductionIsOk(station);

                    // 跳工序校验
                    (operationIsOk, errorcode) = OperationIsOk(code, station, count);

                    if (station.Equals(SystemConstant.NgStationL) || station.Equals(SystemConstant.NgStationR))
                    {
                        bool ngIsSave = orderDao.NgStationIsSave(code, station, "1");

                        ngStationIsGoOut = !ngIsSave;
                    }

                    if (isOk || isSave || productionIsOk || ngStationIsGoOut || operationIsOk)
                    {
                        if (isOk)
                        {
                            // 格式校验报警
                            errorCodes.Add(1100 + count);

                            NgStatus.Add(isOk);
                        }

                        if (isSave)
                        {
                            // 重码报警
                            errorCodes.Add(1110 + count);

                            NgStatus.Add(isSave);
                        }

                        if (productionIsOk)
                        {
                            if (!errorCodes.Contains(1501))
                                // 产量报警
                                errorCodes.Add(1501);

                            NgStatus.Add(productionIsOk);
                        }

                        if (ngStationIsGoOut)
                        {
                            if (!errorCodes.Contains(1502))
                                // 不是NG出站的件，从NG上线报警
                                errorCodes.Add(1502);

                            NgStatus.Add(ngStationIsGoOut);
                        }

                        if (operationIsOk)
                        {
                            errorCodes.Add(errorcode + count);

                            NgStatus.Add(operationIsOk);
                        }
                    }

                    count++;
                }
            }
            catch (Exception ex)
            {
                Tools.ProduceLogTextError($"[{station}]触发校验失败，原因是[{ex.Message}]");

                return (-1, errorCodes);
            }

            if (NgStatus.Count > 0) return (2, errorCodes);

            else return (1, errorCodes);
        }

        /// <summary>
        /// 检测是否存在跳工序
        /// </summary>
        /// <param name="code"></param>
        /// <param name="station"></param>
        /// <returns></returns>
        private (bool, int) OperationIsOk(string code, string station, int count)
        {
            Dictionary<int, string> dictionary = MappingTable.GetLastStation(station);

            if (dictionary == null)
                return (false, 0);

            PartProcess partProcess = orderDao.GetStationData(code, dictionary[count + 1]);

            if (partProcess == null)
            {
                // 无数据
                return (true, 1120);
            }
            else if (DateTimeIsNullOrEmpty(partProcess.StartTime) && !DateTimeIsNullOrEmpty(partProcess.EndTime))
            {
                // 无进有出，默认补齐
                partProcess.StartTime = partProcess.EndTime.AddMinutes(-1);

                orderDao.UpDateStationStartTime(partProcess);

                Tools.ProduceLogTextError($"[{station}]补齐了一条无进有出数据，开始时间[{partProcess.StartTime}]，追溯码[{code}]");

                return (false, 0);
            }
            else if (!DateTimeIsNullOrEmpty(partProcess.StartTime) && DateTimeIsNullOrEmpty(partProcess.EndTime))
            {
                // 有进无出
                return (true, 1130);
            }
            else
            {
                return (false, 0);
            }
        }

        /// <summary>
        /// 判断时间是否为空或者为最小值
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        private bool DateTimeIsNullOrEmpty(DateTime dateTime)
        {
            if (dateTime == null || dateTime == DateTime.MinValue)
                return true;

            return false;
        }

        /// <summary>
        /// 检测重码
        /// </summary>
        /// <param name="code"></param>
        /// <param name="station"></param>
        /// <returns></returns>
        private bool CodeIsSave(string code, string station)
        {
            bool isSave = orderDao.CodeIsSave(code, station);

            if (station.Equals(SystemConstant.OP250L) || station.Equals(SystemConstant.OP250R))
            {
                if (isSave)
                {
                    // 存在重码，检测是否有NG入站记录
                    bool ngIsSave = orderDao.NgStationIsSave(code, station, "2");

                    return !ngIsSave;
                }

                return isSave;
            }
            else
            {
                return isSave;
            }
        }

        /// <summary>
        /// 产量校验
        /// </summary>
        /// <param name="station"></param>
        /// <returns></returns>
        private bool OrderProductionIsOk(string station)
        {
            OrderSingletonModel orderSingletonModel = OrderSingleton.GetOrderId(station);

            if (orderSingletonModel == null)
                return false;

            if (orderSingletonModel.ProducessNumNow >= orderSingletonModel.ProducessNum)
                return true;

            return false;
        }

        #region 私有方法
        /// <summary>
        /// 格式校验
        /// </summary>
        /// <param name="code"></param>
        private bool CodeIsOk(string code)
        {
            // 正则表达式1：匹配第一种格式 "LAC-51010298 5FK 2A230631 X200001 230831 00001"
            Regex regex1 = new Regex(@"^LAD-\d{8} [A-Z0-9]{3} \d{1}[A-Z]{1}\d{6} [A-Z0-9]{1}\d{6} \d{6} \d{5}$");

            // 正则表达式2：匹配第二种格式 "LAC-56010050 01 5FK 2A230631 X200001 230831 A 00001"
            Regex regex2 = new Regex(@"^LAD-\d{8} \d{2} [A-Z0-9]{3} 2A\d{6} [A-Z0-9]{1}\d{6} \d{6} [A-Z] \d{5}$");

            // 正则表达式3：匹配第三种格式 "LAC-84001059 08 240705 A 00001"
            Regex regex3 = new Regex(@"^LAD-\d{8} \d{2} \d{6} [A-Z] \d{5}$");

            // 正则表达式4：匹配第四种格式 "LAC-56010050-1 01 5FK 2A230631 X200001 230831 A 00001"
            Regex regex4 = new Regex(@"^LAD-\d{8}-\d{1} \d{2} [A-Z0-9]{3} 2A\d{6} [A-Z0-9]{1}\d{6} \d{6} [A-Z] \d{5}$");

            bool a = regex1.IsMatch(code);
            bool b = regex2.IsMatch(code);
            bool c = regex3.IsMatch(code);
            bool d = regex4.IsMatch(code);

            if (!(a || b || c || d))
                return true;
            return false;
        }
        #endregion
    }
}
